package org.terukusu.dropboxdownloader;

import org.terukusu.util.Utils;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;

import com.dropbox.client.DropboxAPI;

/**
 * DropBoxへのログインを行ないます。
 *
 * @author Teruhiko Kusunoki&lt;<a href="teru.kusu@gmail.com">teru.kusu@gmail.com</a>&gt;
 *
 */
public class LoginActivity extends Activity implements PrefConstans {
    /**
     * TAG for {@link android.util.Log}
     */
    private static final String TAG = LoginActivity.class.getSimpleName();
    /**
     * Dialog ID
     */
    private static final int DIALOG_PROGRESS = 1;

    /**
     * 実行中の非同期タスク
     */
    private AsyncTask<Object, Integer, Boolean> task;

    /* (non-Javadoc)
     * @see android.app.Activity#onCreate(android.os.Bundle)
     */
    @Override
    @SuppressWarnings("unchecked")
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login);

        SharedPreferences pref = getSharedPreferences(PREF, MODE_PRIVATE);

        //ログイン状態保存チェックボックス
        CheckBox cb = (CheckBox) findViewById(R.id.loginKeepLoginCheck);
        cb.setChecked(pref.getBoolean(PREF_KEEP_LOGIN, false));

        // メアドボックス
        EditText mailEdit = (EditText) findViewById(R.id.loginMailEdit);
        mailEdit.setText(pref.getString(PREF_MAIL, null));

        // ログインタスクから通知を受け取るためのリスナー
        final AsyncTaskListener<Integer, Boolean> asyncTaskListener = new AsyncTaskAdapter<Integer, Boolean>() {

            /* (non-Javadoc)
             * @see android.os.AsyncTask#onPreExecute()
             */
            @Override
            public void onPreExecute() {
                showDialog(DIALOG_PROGRESS);
            }


            /* (non-Javadoc)
             * @see android.os.AsyncTask#onPreExecute()
             */
            @Override
            public void onPostExecute(Boolean result) {
                dismissDialog(DIALOG_PROGRESS);

                if (!result) {
                    // ログイン失敗
                    Toast.makeText(LoginActivity.this, R.string.login_failed, Toast.LENGTH_LONG).show();
                    return;
                }

                // ログイン成功
                DropboxManager dm = DropboxManager.getInstance();
                DropboxAPI.Config config = dm.getConfig();

                // ログイン状態維持関連の処理
                SharedPreferences pref = getSharedPreferences(PREF, MODE_PRIVATE);
                Editor editor = pref.edit();
                boolean isKeepLogin = pref.getBoolean(PREF_KEEP_LOGIN, false);
                if (isKeepLogin) {
                    Log.v(TAG, "saving token, tokenKey = " + config.accessTokenKey + ", tokenSecret = " + config.accessTokenSecret);
                    editor.putString(PREF_ACCESS_TOKEN_KEY, config.accessTokenKey);
                    editor.putString(PREF_ACCESS_TOKEN_SECRET, config.accessTokenSecret);
                } else {
                    editor.remove(PREF_ACCESS_TOKEN_KEY);
                    editor.remove(PREF_ACCESS_TOKEN_SECRET);
                }
                editor.commit();

                // アクティビティ終了
                setResult(RESULT_OK);
                finish();
            }
        };

        // ログインボタン
        Button submitButton = (Button) findViewById(R.id.loginLoginButton);
        submitButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                EditText mailEdit = (EditText) findViewById(R.id.loginMailEdit);
                String mail = mailEdit.getText().toString().trim();
                mailEdit.setText(mail);

                if (Utils.isStringEmpty(mail)) {
                    Toast.makeText(LoginActivity.this, R.string.login_mail_invalid, Toast.LENGTH_LONG).show();
                    return;
                }

                EditText passEdit = (EditText) findViewById(R.id.loginPasswordEdit);
                String pass = passEdit.getText().toString().trim();
                passEdit.setText(pass);

                if (Utils.isStringEmpty(pass)) {
                    Toast.makeText(LoginActivity.this, R.string.login_pass_invalid, Toast.LENGTH_LONG).show();
                    return;
                }

                // 設定関連
                SharedPreferences pref = getSharedPreferences(PREF, MODE_PRIVATE);
                Editor editor = pref.edit();

                // ログイン状態保存設定
                CheckBox keepLoginCheck = (CheckBox) findViewById(R.id.loginKeepLoginCheck);
                boolean isKeepLogin = keepLoginCheck.isChecked();
                editor.putBoolean(PREF_KEEP_LOGIN, isKeepLogin);

                if (isKeepLogin) {
                    // メアド保存
                    editor.putString(PREF_MAIL, mail);
                } else {
                    // アクセストークン削除
                    editor.remove(PREF_ACCESS_TOKEN_KEY);
                    editor.remove(PREF_ACCESS_TOKEN_SECRET);
                }

                editor.commit();

                // ログイン処理を非同期で行う
                Log.v(TAG, "trying password auth..");
                task =  new PasswordAuthTask();
                task.setAsyncTaskListener(asyncTaskListener);
                Log.v(TAG, "mail=" + mail + ", pass=" + pass);
                task.execute(mail, pass);
            }
        });

        if (getLastNonConfigurationInstance() != null) {
            Log.v(TAG, "nonConfigurationInstance is not null.");

            // コンフィグチェンジ後のUI再構築
            task = (AsyncTask<Object, Integer, Boolean>) getLastNonConfigurationInstance();
            task.setAsyncTaskListener(asyncTaskListener);

            return;
        }

        // アクセストークンが保存されていればトークン認証を試みる
        String tokenKey = pref.getString(PREF_ACCESS_TOKEN_KEY, null);
        String tokenSecret = pref.getString(PREF_ACCESS_TOKEN_SECRET, null);
        Log.v(TAG, "tokenKey = " + tokenKey+ ", tokenSecret = " + tokenSecret);

        if (!Utils.isStringEmpty(tokenKey) && !Utils.isStringEmpty(tokenSecret)) {
            Log.v(TAG, "trying token auth..");
            task = new TokenAuthTask();
            task.setAsyncTaskListener(asyncTaskListener);
            task.execute(tokenKey, tokenSecret);
            return;
        }
    }

    /* (non-Javadoc)
     * @see android.app.Activity#onRetainNonConfigurationInstance()
     */
    @Override
    public Object onRetainNonConfigurationInstance() {
        Log.v(TAG, "[" + Thread.currentThread().getName() + ":" + Thread.currentThread().getId()
                + "] onRetainNonConfigurationInstance() called: hashCode=" + hashCode());

        if (task != null) {
            task.setAsyncTaskListener(null);
            return task;
        }

        return null;
    }

    /* (non-Javadoc)
     * @see android.app.Activity#onStart()
     */
    @Override
    protected void onStart() {
        super.onStart();
        Log.v(TAG, "[" + Thread.currentThread().getName() + ":" + Thread.currentThread().getId()
                + "] onStart() called: hashCode=" + hashCode());
    }

    /* (non-Javadoc)
     * @see android.app.Activity#onDestroy()
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.v(TAG, "[" + Thread.currentThread().getName() + ":" + Thread.currentThread().getId()
                + "] onDestroy() called: hashCode=" + hashCode());
    }

    /* (non-Javadoc)
     * @see android.app.Activity#onCreateDialog(int)
     */
    @Override
    protected Dialog onCreateDialog(int id) {
        Log.v(TAG, "[" + Thread.currentThread().getName() + ":" + Thread.currentThread().getId()
                + "] onCreateDialog() called: hashCode=" + hashCode());

        Log.v(TAG, "craeting dialog: id=" + id);
        switch (id) {
        case DIALOG_PROGRESS:
            ProgressDialog d = new ProgressDialog(LoginActivity.this);
            d.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            d.setCancelable(false);
            d.setMax(100);
            d.setMessage(getText(R.string.login_progress));
            Log.v(TAG, "dialog created: hashCode=" + d.hashCode());
            return d;
        default:
            return null;
        }
    }

    /* (non-Javadoc)
     * @see android.app.Activity#onPrepareDialog(int, android.app.Dialog)
     */
    @Override
    protected void onPrepareDialog(int id, Dialog dialog) {
        super.onPrepareDialog(id, dialog);
        Log.v(TAG, "[" + Thread.currentThread().getName() + ":" + Thread.currentThread().getId()
                + "] onPrepareDialog() called: hashCode=" + hashCode() + ", Dialog id=" + id + ", Dialog hashCode=" + dialog.hashCode());

        switch (id) {
        case DIALOG_PROGRESS:
            ((ProgressDialog) dialog).setProgress(0);
            break;
        }
    }

    /**
     * パスワード認証処理を実行するための非同期タスク
     *
     * @author Teruhiko Kusunoki&lt;<a href="teru.kusu@gmail.com">teru.kusu@gmail.com</a>&gt;
     *
     */
    private class PasswordAuthTask extends AsyncTask<Object, Integer, Boolean> {
        /**
         * TAG for {@link android.util.Log}
         */
        private final String TAG = LoginActivity.PasswordAuthTask.class.getSimpleName();

        /* (non-Javadoc)
         * @see android.os.AsyncTask#doInBackground(Params[])
         */
        @Override
        protected Boolean doInBackground(Object... params) {
            Log.v(TAG, "doInbackground() called on thread: [" + Thread.currentThread().getId() + "] " + Thread.currentThread().getName());
            DropboxManager dm = DropboxManager.getInstance();
            return dm.authenticate((String)params[0], (String) params[1]);
        }
    }

    /**
     * トークン認証処理を実行するための非同期タスク
     *
     * @author Teruhiko Kusunoki&lt;<a href="teru.kusu@gmail.com">teru.kusu@gmail.com</a>&gt;
     */
    private class TokenAuthTask extends AsyncTask<Object, Integer, Boolean> {
        /* (non-Javadoc)
         * @see android.os.AsyncTask#doInBackground(Params[])
         */
        @Override
        protected Boolean doInBackground(Object... params) {
            Log.v(TAG, "doInbackground() called on thread: [" + Thread.currentThread().getId() + "] " + Thread.currentThread().getName());
            DropboxManager dm = DropboxManager.getInstance();
            return dm.authenticateToken((String)params[0], (String) params[1]);
        }
    }
}
